package com.sayimo.maker.commons.ali.pay;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.sayimo.framework.exception.ServiceException;
import com.sayimo.maker.commons.Constant;
import com.sayimo.maker.commons.utils.JSONUtil;
import com.sayimo.maker.commons.utils.PropertiesUtils;
import com.sayimo.maker.commons.utils.RequestUtils;


public class AliWapPay {
	
	private static Log logger = LogFactory.getLog(AliWapPay.class);

	    //一。支付接口
		//1.生成订单信息，发送支付请求到支付宝系统
		//2.展示支付信息--输入密码确认支付
		//3.完成支付--（支付宝）页面返回支付接口return_url/后台通知支付结果notify_url
		//4.对返回数据进行处理-->展示订单信息
	public static Map aliWapPayOrder(Map _paramsMap) throws ServiceException, AlipayApiException, IOException {
		Map resultMap = new HashMap();
		   
		//基本参数设置,提供给支付宝的请求参数app_id method charset sign_type sign timestamp version biz_content
		Map<String,String> baseParam = new HashMap<>();
		baseParam.put("app_id", AlipayUtil.ALIPAY_APPID);//合作者身份id
		baseParam.put("method", "alipay.trade.wap.pay");
		baseParam.put("charset", "utf-8");//商户使用网站的编码格式
		baseParam.put("sign_type", "RSA2");//签名方式
		baseParam.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		baseParam.put("version", "1.0");
		
		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
		HttpServletRequest request = servletRequestAttributes.getRequest();
        
        
		//业务参数设置
		Map<String,Object> businessParam = new HashMap<>();
		String subject= (String) _paramsMap.get("goodsName");
        String out_trade_no= (String) _paramsMap.get("ordersNo");
        String total_amount= String.valueOf(_paramsMap.get("payPrice"));
        //subject out_trade_no total_amount product_code
        businessParam.put("subject", subject); //商品名称
        businessParam.put("out_trade_no", out_trade_no); //支付宝合作商户唯一订单号
        businessParam.put("product_code", "QUICK_WAP_PAY"); //支付类型
        businessParam.put("total_amount", total_amount); //交易金额
        
    
        
        
       
        //makerWap/view/default/payresult.html--如果是研发https://ggschool.sayimo.cn
       	baseParam.put("notify_url",PropertiesUtils.getValue("SERVER_URL") + request.getContextPath()+"/orders/callbackalipay");
        logger.info("支付宝回掉调地址  = " + PropertiesUtils.getValue("SERVER_URL") + request.getContextPath()+"/orders/callbackalipay");
        baseParam.put("return_url", PropertiesUtils.getValue("SERVER_URL") +"makerWap/view/default/payresult.html");
        //baseParam.put("return_url", "https://www.baidu.com");
        logger.info("支付成功跳转地址  = " + PropertiesUtils.getValue("SERVER_URL") +"makerWap/view/default/payresult.html");
        
        //填充业务参数    
        baseParam.put("biz_content",JSON.toJSONString(businessParam));
        logger.info("biz_content = " + JSON.toJSONString(businessParam));
        
        //对未签名原始字符串进行签名
        String _param=AlipaySignature.getSignContent(baseParam);
        String rsaSign = AlipaySignature.rsaSign(_param, AlipayUtil.APP_PRIVATE_KEY, "utf-8","RSA2");
        //String  sign=URLEncoder.encode(rsaSign, "utf-8");//............做个标识
        baseParam.put("sign", rsaSign);   //商户请求参数的签名串   
        logger.info("rsaSign = " + rsaSign);
        
      //支付宝异步回调参数
        {
 	        Map<String, Object> passBackMap = new HashMap<>();
 	        Set<String> keys = _paramsMap.keySet();
 	        for (String key : keys) {
 				if (!key.startsWith("_")) {
 					continue;
 				}
 				
 				passBackMap.put(key, _paramsMap.get(key));
 			}
 	        if (MapUtils.isNotEmpty(passBackMap)) {
 	        	String passBackParams = JSONUtil.writeValueAsString(passBackMap);
 		        logger.info("passBackParams = " + passBackParams);
 				String passback_params = URLEncoder.encode(passBackParams,"utf-8"); 
                businessParam.put("passback_params",passback_params);  //公用回传参数，如果请求时传递了该参数，则返回给商户时会回传该参数。支付宝会在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝
                logger.info("businessParam = " + businessParam);
 	        }
         }
        
        String form=getSignEncodeUrl(baseParam, true);
        // String form =JSON.toJSONString(baseParam);
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("orderStr", form);
        dataMap.put("ordersNo", String.valueOf(_paramsMap.get("ordersNo")));
        if(String.valueOf(_paramsMap.get("ordersNo")).substring(0, 3).equals("005")){
        	dataMap.put("consumerOrdersNo", String.valueOf(_paramsMap.get("consumerOrdersNo")));
        }
		logger.info("form = " + form);
		resultMap.put(Constant.STATUS, Constant.STATUS_SUCCESS);
		resultMap.put(Constant.DATA, dataMap);	
		return resultMap;	
    }
	
	//url拼接
	private static String getSignEncodeUrl(Map<String, String> map, boolean isEncode) {
		String sign = map.get("sign");
		String encodedSign = "";
		if (map !=null && map.size() > 0) {
			map.remove("sign");
			List<String> keys = new ArrayList<String>(map.keySet());
			// key排序
			Collections.sort(keys);

			StringBuilder authInfo = new StringBuilder();

			boolean first = true;// 是否第一个
			for (String key: keys) {
				if (first) {
					first = false;
				} else {
					authInfo.append("&");
				}
				authInfo.append(key).append("=");
				if (isEncode) {
					try {
						authInfo.append(URLEncoder.encode(map.get(key), AlipayConstants.CHARSET_UTF8));
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
				} else {
					authInfo.append(map.get(key));
				}
			}

			try {
				encodedSign = authInfo.toString() + "&sign=" + URLEncoder.encode(sign, AlipayConstants.CHARSET_UTF8);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}

		return encodedSign.replaceAll("\\+", "%20");
	}
	//异步通知验签
	public static Map<String, Object> callbackAliWapPay(HttpServletRequest request)throws Exception {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		try {
	        Map<String, String> callbackParamMap = RequestUtils.bindRequestParam(request, HashMap.class);
	        callbackParamMap.remove("sign");
	        callbackParamMap.remove("sign_type");
	        logger.info("callbackParamMap = " + callbackParamMap);
	        logger.info("callbackParamMap = " + JSONUtil.writeValueAsString(callbackParamMap));
	        
	        boolean signVerified = AlipaySignature.rsaCheckV1(callbackParamMap, AlipayUtil.ALIPAY_PUBLIC_KEY,
	                AlipayConstants.CHARSET_UTF8,"RSA2"); // 校验签名是否正确
	        
	        if (!signVerified) {
	        	resultMap.put(Constant.STATUS, Constant.STATUS_ERROR);
	        	return resultMap;
			}
	        logger.info("支付宝支付回调验签，  signVerified = " + signVerified);
	        
	        if(!"TRADE_SUCCESS".equals(callbackParamMap.get("trade_status")) 
	        		&& !"TRADE_FINISHED".equals(callbackParamMap.get("trade_status"))){
	        	resultMap.put(Constant.STATUS, Constant.STATUS_ERROR);
	        	return resultMap;
	        }
	        
	        if (callbackParamMap.containsKey("passback_params")) {
	        	String passbackParams = callbackParamMap.get("passback_params");
	        	passbackParams = URLDecoder.decode(URLDecoder.decode(passbackParams, "UTF-8"), "UTF-8");
	        	logger.info("passbackParams = " + passbackParams);
	        	Map passBackMap = JSONUtil.readValueToMap(passbackParams);
	        	resultMap.putAll(passBackMap);
			}
	        
	        logger.info("callbackParamMap = " + callbackParamMap);
	        logger.info("callbackParamMap = " + JSONUtil.writeValueAsString(callbackParamMap));
	        
	        String appId = callbackParamMap.get("app_id"), seller_id = callbackParamMap.get("seller_id"),
	        		_payPrice = String.valueOf(resultMap.get("_payPrice"));
	        		
	        
	        Double jPayPrice = Double.valueOf(_payPrice),
	        		total_amount = Double.valueOf(String.valueOf(callbackParamMap.get("total_amount")));
	        logger.info("total_amount = " + total_amount + ", _payPrice = " + _payPrice);
	        
	        // 比对金额
	        if (!resultMap.containsKey("_payPrice") || jPayPrice.compareTo(total_amount) != 0) {
	        	resultMap.put(Constant.STATUS, Constant.STATUS_ERROR);
	        	return resultMap;
			}
	        
	        // 不是支付宝回调（参数被篡改）
	        if(!AlipayUtil.ALIPAY_APPID.equals(appId) || !AlipayUtil.ALIPAY_SELLERID.equals(seller_id)){
	        	resultMap.put(Constant.STATUS, Constant.STATUS_ERROR);
	        	return resultMap;
	       	}
	        
	        resultMap.put(Constant.STATUS, Constant.STATUS_SUCCESS);
	        resultMap.put("ordersNo", callbackParamMap.get("out_trade_no")); // 订单号
	        logger.info("resultMap = " + resultMap);
	        return resultMap;
		}catch (Exception e) {
			e.printStackTrace();
			throw new ServiceException(e);
		}
	}

	
	//二。交易关闭接口
	//1.请求关闭订单
	//2.返回处理结果
	public static Boolean closeAliWapPayTrade(String out_trade_no) throws AlipayApiException{
		AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
				AlipayUtil.ALIPAY_APPID,AlipayUtil.APP_PRIVATE_KEY,"json",AlipayConstants.CHARSET_UTF8,
				AlipayUtil.ALIPAY_PUBLIC_KEY,"RSA2");
		AlipayTradeCloseRequest alipayCloseRequest=new AlipayTradeCloseRequest();
		Map<String, Object> param = new HashMap<>();
	    param.put("out_trade_no", out_trade_no); // 商户订单号
		alipayCloseRequest.setBizContent(JSON.toJSONString(param));
		AlipayTradeCloseResponse response = alipayClient.execute(alipayCloseRequest);
		boolean flag=false;
		if(response.isSuccess()){
		    flag=true;
		} else {
		    flag=false;
		};
		return flag;	
	}
	
	
	
	//三。交易查询接口
	//1.发起退款请求
	//2.返回支付结果
	public static boolean validAliWapPayTradeQuery(String out_trade_no) throws AlipayApiException{
		AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
				AlipayUtil.ALIPAY_APPID,AlipayUtil.APP_PRIVATE_KEY,"json",AlipayConstants.CHARSET_UTF8,
				AlipayUtil.ALIPAY_PUBLIC_KEY,"RSA2");
		AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest(); // 统一收单线下交易查询
		 // 只需要传入业务参数
        Map<String, Object> param = new HashMap<>();
        param.put("out_trade_no", out_trade_no); // 商户订单号
		alipayRequest.setBizContent(JSON.toJSONString(param));
		boolean flag = false; // 查询状态
		
		AlipayTradeQueryResponse response = alipayClient.execute(alipayRequest);
		logger.info("response = " + JSONUtil.writeValueAsString(response));
		if(response.isSuccess()){
			if ("10000".equals(response.getCode())) {
				System.out.println(response.getCode());
				if("TRADE_SUCCESS".equals(response.getTradeStatus())){
					flag = true;
				}
			}
			
		} else {
			flag = false;
		}
		return flag;
	}
	
	
	//四。支付退款接口
	//1.发起退款请求
	//2.返回退款结果
  public static String aliwappayTradeRefund(String out_trade_no,String refund_amount) throws AlipayApiException{
	AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
			AlipayUtil.ALIPAY_APPID,AlipayUtil.APP_PRIVATE_KEY,"json",AlipayConstants.CHARSET_UTF8,
			AlipayUtil.ALIPAY_PUBLIC_KEY,"RSA2");
	AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest(); // 支付宝退款请求
	 // 只需要传入业务参数
    Map<String, Object> param = new HashMap<>();
    param.put("out_trade_no", out_trade_no); // 商户订单号
    param.put("refund_amount", refund_amount);// 退款金额
	alipayRequest.setBizContent(JSON.toJSONString(param));
	AlipayTradeRefundResponse response = alipayClient.execute(alipayRequest);
	logger.info("response = " + JSONUtil.writeValueAsString(response));
	if(response.isSuccess()){
		if ("10000".equals(response.getCode())) {
			System.out.println(response.getCode());
			return Constant.SUCCESS;
		}
		
	  } 
	return Constant.ERROR;
	}	
}
	//五。退款查询接口
	//1.发起退款查询请求
	//2.返回退款状态
	
	
	

